#!/usr/bin/python
# -*- coding: UTF-8 -*-
'''
Menu's for MyGarden
Created on 21 jun 2011

@author: Joakim Lindskog

Copyright (c) 2011 Joakim Lindskog

This file is part of MyGarden.

    MyGarden is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    MyGarden is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with MyGarden.  If not, see <http://www.gnu.org/licenses/>.
'''
from cocos import menu, scene, text, layer, actions
import sys, pyglet, game, icon, math, util, time, os, glob, main, gettext
from babel import Locale
from gardenbase import gardensprite
from pyglet.window import key
from cocos.director import director
from util import config
from plants import plant

class MainMenu(menu.Menu):
    '''
    MainMenu represents the main menu of the game
    '''
    is_event_handler = True
    
    about_text = _("about_text")

    def __init__(self):
        '''
        Constructor
        '''
        super(MainMenu, self).__init__();
        self.gameStarted = False
        
        # Settings
        pyglet.resource.add_font('Carousel.ttf')
        pyglet.resource.add_font('DroidSans.ttf')
        self.font_item['font_name'] = 'Carousel'
        self.font_item_selected['font_name'] = 'Carousel'
        self.font_item['font_size'] = 38
        self.font_item_selected['font_size'] = 48
        self.font_item['color'] = (224,224,224,255)
        self.language_changed = False
        
        # Menu options
        self.list = [];
        self.startContinue = menu.MenuItem(_("menu_start"), self.startGame)
        self.list.append(self.startContinue);
        self.restartOption = menu.MenuItem(_("menu_restart"), self.restart)
        self.list.append(self.restartOption)
        self.menu_tutorial = menu.MenuItem(_("menu_tutorial"), self.tutorial)
        self.list.append(self.menu_tutorial)
        
        # Find available languages
        localedir = main.localedir
        arr = glob.glob(os.path.join(localedir, "*", "*", "mygarden.mo"))
        
        languages = []
        translations = []
        lang_index = 0
        i = 0
        lang_found = False
        for l in arr:
            l = l.replace(localedir, '').split(os.path.sep)[1]
            if main.t.info()['language'] == l:
                lang_index = i
                lang_found = True
            # Create translation
            translations.append(gettext.translation("mygarden", localedir,\
                             languages=[l], fallback=True, codeset="utf-8"))
            larr = l.split("_")
            loc = Locale(larr[0], larr[1])
            l = loc.languages[loc.language]+" ["+larr[1]+"]"
            languages.append(l.title())
            i+=1
        if not lang_found:
            i = 0
            for l in arr:
                l = l.replace(localedir, '').split(os.path.sep)[1].split("_")[0]
                if main.t.info()['language'] == l:
                    lang_index = i
                    lang_found = True
                    break
                i+=1
            
        self.list.append(ChoiceMenuItem("", self.language, languages, translations=translations,\
                                        default_item=lang_index))
        self.menu_scores = menu.MenuItem(_("menu_scores"), self.highscores)
        self.list.append(self.menu_scores)
        self.menu_about = menu.MenuItem(_("menu_about"), self.about)
        self.list.append(self.menu_about)
        self.menu_exit = menu.MenuItem(_("menu_exit"), self.exit)
        self.list.append(self.menu_exit);
        self.create_menu(self.list);
        self.restartOption.item.color = (90,90,90,220)
        self.restartOption.item_selected.color = (110,110,110,220)
        self.on_quit = lambda: self.exit()
        
        # Scene
        self.scene = scene.Scene()
        
        # Add background
        background = gardensprite.GardenSprite(util.load_image("start_screen.jpg"))
        background.position = config.SCREEN_WIDTH/2, config.SCREEN_HEIGHT/2
        self.scene.add(background,0)
        # Add menu
        self.position = 0, -50
        self.scene.add(self,2)
        
        # Create title label
        title_label = text.Label("My Garden", font_name="Carousel", font_size=56, \
                                 anchor_x="center", anchor_y="center");
        title_label.position = 400, 530;
        self.scene.add(title_label,2);
        # Create footer label
        footer_label = text.RichLabel("Copyright {#169}2011 Joakim Lindskog", font_name="Droid Sans",\
                                      font_size=16, anchor_x="center", anchor_y="center")
        footer_label.position = 400, 40
        self.scene.add(footer_label,2)
        
        # Text overlay
        self.overlay = TextOverlay(self.scene)
        self.overlay.visible = False
        self.scene.add(self.overlay,50)
    
    def startGame(self, tutorial=False):
        '''
        Starts the game
        
        @param tutorial: whether to start the tutorial
        @type tutorial: boolean
        '''
        if not self.gameStarted:
            game.Game(tutorial, self.language_changed)
            self.gameStarted = True
            self.startContinue.item.text = _("menu_continue")
            self.startContinue.item_selected.text = _("menu_continue")
            self.restartOption.item.color = (192,192,192,255)
            self.restartOption.item_selected.color = (255,255,255,255)
        else:
            game.Game().resumeGame(True, self.language_changed)
    
    def restart(self, tutorial=False):
        '''
        Restarts the game
        
        @param tutorial: whether to start the tutorial
        @type tutorial: boolean
        '''
        if self.gameStarted:
            game.Game().restartGame(tutorial=tutorial, language_changed=self.language_changed)
    
    def tutorial(self):
        '''
        Starts the tutorial
        '''
        if not self.gameStarted:
            self.startGame(True)
        else:
            self.restart(True)
    
    def language(self, lang):
        '''
        Changes the language
        '''
        global t
        t = lang
        t.install(unicode=1)
        self.reload_text()
        self.language_changed = True
        
    def highscores(self):
        '''
        Displays the highscores
        '''
        self.add(self.high_scores, z=150)
    
    def about(self):
        '''
        Displays the game credits
        '''
        self.overlay.setText(MainMenu.about_text)
        self.overlay.show()
    
    def exit(self):
        '''
        Exits the game
        '''
        sys.exit()
        
    def reload_text(self):
        '''
        Reloads all translated text
        '''
        # Menu items
        if self.gameStarted:
            self.startContinue.item.text = _("menu_continue")
            self.startContinue.item_selected.text = _("menu_continue")
        else:
            self.startContinue.item.text = _("menu_start")
            self.startContinue.item_selected.text = _("menu_start")
        self.restartOption.item.text = _("menu_restart")
        self.restartOption.item_selected.text = _("menu_restart")
        self.menu_tutorial.item.text = _("menu_tutorial")
        self.menu_tutorial.item_selected.text = _("menu_tutorial")
        self.menu_scores.item.text = _("menu_scores")
        self.menu_scores.item_selected.text = _("menu_scores")
        self.menu_about.item.text = _("menu_about")
        self.menu_about.item_selected.text = _("menu_about")
        self.menu_exit.item.text = _("menu_exit")
        self.menu_exit.item_selected.text = _("menu_exit")
        # About text
        MainMenu.about_text = _("about_text")
        # Highscores text
        self.high_scores.reset_text()
        # Month names
        util.config.reload_months()
    
    def is_menu_focused(self):
        '''
        @return: whether the menu is focused
        @rtype: boolean
        '''
        return not self.overlay.visible and not self.high_scores.visible
    
    def on_key_press(self, symbol, modifiers):
        if symbol == key.ESCAPE or symbol == key.RETURN:
            if self.overlay.visible:
                self.overlay.hide()
                return True
        if self.is_menu_focused():
            return super(MainMenu, self).on_key_press(symbol, modifiers)
        
    def on_text(self, text):
        if self.is_menu_focused():
            return super(MainMenu, self).on_text(text)
        
    def on_mouse_release(self, x, y, buttons, modifiers):
        if self.is_menu_focused():
            return super(MainMenu, self).on_mouse_release(x, y, buttons, modifiers)
        else:
            self.overlay.hide()
        
    def on_mouse_motion(self, x, y, dx, dy):
        if self.is_menu_focused():
            return super(MainMenu, self).on_mouse_motion(x, y, dx, dy)
        
    def on_enter(self):
        super(MainMenu, self).on_enter()
        # Music
        self.scene.load_music(util.get_sound_path('mygarden.ogg'), repeat=-1)
        # Start music
        self.scene.play_music(loops=-1)
        
        # High scores
        self.high_scores = game.HighscoreLayer()

class ChoiceMenuItem(menu.MultipleMenuItem):
    '''
    A MultipleMenuItem that "goes around"
    '''
    
    def __init__(self, label, callback_func, items, default_item=0, translations=[]):
        self.translations = translations
        super(ChoiceMenuItem, self).__init__(label, callback_func, items, default_item)
        
    def on_key_press(self, symbol, modifiers):
        if symbol == key.LEFT:
            self.idx = self.idx-1 if (self.idx-1)>=0 else len(self.items)-1
        elif symbol in (key.RIGHT, key.ENTER):
            self.idx = self.idx+1 if (self.idx+1)<len(self.items) else 0

        if symbol in (key.LEFT, key.RIGHT, key.ENTER):
            self.item.text = self._get_label()
            self.item_selected.text = self._get_label()
            self.callback_func(self.translations[self.idx])
            return True

class TextOverlay(layer.ColorLayer):
    '''
    TextOverlay is a window for showing text
    '''
    
    def __init__(self, scene):
        '''
        Constructor
        '''
        super(TextOverlay, self).__init__(240,240,240,0)
        self.scene = scene
        self.width = int(config.SCREEN_WIDTH*.7)
        self.height = int(config.SCREEN_HEIGHT*.7)
        self.position = (config.SCREEN_WIDTH-self.width)/2, (config.SCREEN_HEIGHT-self.height)/2
        
        self.text = text.HTMLLabel("", anchor_x='left', anchor_y='top', multiline=True, width=self.width-20, height=self.height-20)
        self.text.position = 10, self.height-10
        self.add(self.text)
        
    def setText(self, text):
        '''
        Sets the text of the overlay
        
        @param text: the text to set
        @type text: string
        '''
        self.text.element.text = text
    
    def show(self):
        '''
        Shows the overlay
        '''
        self.do(actions.Show() + actions.FadeTo(240, .5))
        
    def hide(self):
        '''
        Hides the overlay
        '''
        self.do(actions.FadeTo(0, .5) + actions.Hide())

class GameMenu(layer.ColorLayer):
    '''
    The main user interface menu
    '''
    def __init__(self):
        '''
        Constructor
        '''
        super(GameMenu, self).__init__(220, 210, 210, 180)
        
        # Create background
        self.width = 90
        self.height = config.SCREEN_HEIGHT
        self.position = 0,0
        
        # Create menu windows
        self.windows = []
        self.seeds_window = SeedsWindow()
        self.add(self.seeds_window)
        self.seeds_window.visible = False
        self.seeds_window.opacity = 0
        self.windows.append(self.seeds_window)
        
        # Create tools
        from tools import watering_can, fertiliser, shovel
        self.water_tool = watering_can.WateringCan()
        self.fert_grass_tool = fertiliser.Grass()
        self.harvest_tool = shovel.HarvestShovel()
        
        # Create menu icons
        self.icons = []
        # Seeds icon
        self.seeds_icon = icon.Icon("seeds", util.load_image('seeds.png'),
                                    lambda x,y: self.seeds_window.toggle())
        self.seeds_icon.position = 45, config.SCREEN_HEIGHT-45
        self.seeds_icon.tooltip_text = _("icon_seeds")
        self.seeds_icon.type = "main_menu"
        self.icons.append(self.seeds_icon)
        self.add(self.seeds_icon, 5)
        # Watering can icon
        self.water_icon = icon.Icon("water", util.load_image('watering_can_icon.png'),
                                    lambda x,y: game.Game().select_tool(self.water_tool, x, y))
        self.water_icon.position = 45, config.SCREEN_HEIGHT-135
        self.water_icon.tooltip_text = _("icon_water")
        self.water_icon.type = "main_menu"
        self.icons.append(self.water_icon)
        self.add(self.water_icon)
        # Fertiliser icon
        self.fert_icon = icon.Icon("fertiliser", util.load_image('fertiliser_icon.png'),
                                    lambda x,y: game.Game().select_tool(self.fert_grass_tool, x, y))
        self.fert_icon.position = 45, config.SCREEN_HEIGHT-225
        self.fert_icon.tooltip_text = _("icon_fertiliser")
        self.fert_icon.type = "main_menu"
        self.icons.append(self.fert_icon)
        self.add(self.fert_icon)
        # Harvest icon
        self.harvest_icon = icon.Icon("harvest", util.load_image('harvest_icon.png'),
                                      lambda x,y: game.Game().select_tool(self.harvest_tool, x, y))
        self.harvest_icon.position = 45, config.SCREEN_HEIGHT-315
        self.harvest_icon.tooltip_text = _("icon_harvest")
        self.harvest_icon.type = "main_menu"
        self.icons.append(self.harvest_icon)
        self.add(self.harvest_icon)
        # Menu icon
        self.menu_icon = icon.Icon("menu", util.load_image('menu_icon.png'),
                                   lambda x,y: director.pop())
        self.menu_icon.position = 45, config.SCREEN_HEIGHT-405
        self.menu_icon.tooltip_text = _("icon_menu")
        self.menu_icon.type = "main_menu"
        self.icons.append(self.menu_icon)
        self.add(self.menu_icon)
        
    def on_mouse_press(self, x, y, button, modifiers):
        # Delegate mouse press to icons and windows
        for ic in self.icons+self.windows:
            if ic.on_mouse_press(x, y, button, modifiers):
                return True
        return False
    
    def on_mouse_motion(self, x, y, dx, dy):
        # Delegate mouse motion to icons and windows
        for ic in self.icons+self.windows:
            if ic.on_mouse_motion(x, y, dx, dy):
                return True
        return False
    
    def resetMenu(self):
        '''
        Resets the menu
        '''
        for window in self.windows:
            if window.visible:
                window.toggle()
    
    def reset_text(self):
        '''
        Resets translated text
        '''
        self.seeds_icon.tooltip_text = _("icon_seeds")
        self.water_icon.tooltip_text = _("icon_water")
        self.fert_icon.tooltip_text = _("icon_fertiliser")
        self.harvest_icon.tooltip_text = _("icon_harvest")
        self.menu_icon.tooltip_text = _("icon_menu")
        self.seeds_window.reset_text()
            
class MenuWindow(layer.ColorLayer):
    '''
    Base class for menu windows
    '''
    def __init__(self):
        '''
        Constructor
        '''
        super(MenuWindow, self).__init__(220, 210, 210, 180)
        self.width = int((config.SCREEN_WIDTH-90)*0.9)
        self.height = int(config.SCREEN_HEIGHT*0.8)
        self.position = 45+(config.SCREEN_WIDTH-self.width)/2, (config.SCREEN_HEIGHT-self.height)/2
        
    def toggle(self):
        '''
        Toggles the visibility of the menu window
        '''
        if(not self.visible):
            self.do(actions.Show() + actions.FadeTo(180, 0.2))
            for child in self.children:
                child[1].do(actions.Show() + actions.FadeIn(0.2))
        else:
            self.do(actions.FadeTo(0, 0.2) + actions.Hide())
            for child in self.children:
                child[1].do(actions.FadeOut(0.2) + actions.Hide())
        
class SeedsWindow(MenuWindow):
    '''
    Window for selecting seeds to sow
    '''
    def __init__(self):
        '''
        Constructor
        '''
        super(SeedsWindow, self).__init__()
        # Show all available plants
        self.icons = []
        for v in plant.list:
            ic = icon.Icon(v.name, v.icon_image, lambda ref, x, y: game.Game().select_seed(ref, x, y))
            ic.tooltip_text = unicode("<font size='5'>"+str(v.name)+"</font><br>", "UTF-8")+\
                _("germination_time")+unicode(": "+str(v.days_as_seed)+" ", "UTF-8")+_("days")+unicode("<br>", "UTF-8")+\
                _("total_growing_time")+unicode(": "+str(v.days_as_seed+v.days_until_ripe)+" ", "UTF-8")+_("days")+unicode("<br>", "UTF-8")+\
                _("plant_distance")+unicode(": "+str(v.plant_distance)+" cm<br>", "UTF-8")+\
                _("min_temperature")+unicode(": "+str(v.min_temperature)+"°C", "UTF-8")
            ic.ref = v
            ic.type = "seeds_window"
            self.icons.append(ic)
        
        i = 0
        for ic in self.icons:
            ic.position = (i%(self.width/(ic.width+10)))*(ic.width+10)+10+ic.width/2, self.height-(math.floor(i/(self.width/ic.width+10))*(ic.height-10)+10+ic.height/2)
            self.add(ic, 5)
            i+=1
            
    def reset_text(self):
        '''
        Resets translated text
        '''
        i = 0
        for ic in self.icons:
            name_found = False
            v = plant.list[i]
            # Check for localised name
            for n in plant.plant_names[v.id]:
                arr = n.split(":")
                if t.info()['language'] == arr[0]:
                    v.name = arr[1]
                    name_found = True
                    break
            if not name_found:
                for n in plant.plant_names[v.id]:
                    arr = n.split(":")
                    if t.info()['language'] == arr[0].split("_")[0]:
                        v.name = arr[1]
                        name_found = True
                        break
            if not name_found:
                v.name = plant.plant_names[v.id][0].split(":")[1]
            ic.tooltip_text = unicode("<font size='5'>"+str(v.name)+"</font><br>", "UTF-8")+\
                _("germination_time")+unicode(": "+str(v.days_as_seed)+" ", "UTF-8")+_("days")+unicode("<br>", "UTF-8")+\
                _("total_growing_time")+unicode(": "+str(v.days_as_seed+v.days_until_ripe)+" ", "UTF-8")+_("days")+unicode("<br>", "UTF-8")+\
                _("plant_distance")+unicode(": "+str(v.plant_distance)+" cm<br>", "UTF-8")+\
                _("min_temperature")+unicode(": "+str(v.min_temperature)+"°C", "UTF-8")
            i+=1
            
    def on_mouse_press(self, x, y, button, modifiers):
        # Delegate to icons
        if not self.visible: return False
        for ic in self.icons:
            if(ic.on_mouse_press(x, y, button, modifiers)):
                self.toggle()
                return True
        return False
            
    def on_mouse_motion(self, x, y, dx, dy):
        # Delegate to icons
        if not self.visible: return False
        for ic in self.icons:
            if ic.on_mouse_motion(x, y, dx, dy):
                return True
        return False
            
class ToolTip(layer.ColorLayer):
    '''
    ToolTip represents a simple tooltip window
    '''
    
    def __init__(self, txt):
        '''
        Constructor
        '''
        super(ToolTip, self).__init__(220, 210, 210, 180)
        self.width = 180
        self.height = 75
        self.anchor = 0, self.height
        self.num_chars = 18
        self.char_height = 21
        self.char_width = 10
        self.padding = 5
        self.label = text.HTMLLabel(text=txt,
                                anchor_x='left',
                                anchor_y='top',
                                multiline=True,
                                width=260)
        self.label.position = self.padding, self.height-self.padding
        self.add(self.label)
        
    def setText(self, txt, height=None, width=None):
        '''
        Sets the text of the tooltip
        
        @param txt: the text to set
        @type txt: string
        
        @param height: the height of the tooltip window
        @type height: int
        
        @param width: the width of the tooltip window
        @type width: int
        '''
        self.label.element.text = "<font face='Droid Sans' size='3'>"+txt+"</font>"
                
class EndMenu(menu.Menu):
    '''
    The menu shown when a year has ended
    '''
    def __init__(self, parent):
        '''
        Constructor
        '''
        super(EndMenu, self).__init__()
        self.end_layer = parent
        self.font_item['font_name'] = 'Carousel'
        self.font_item_selected['font_name'] = 'Carousel'
        list = [menu.MenuItem(_("end_to_menu"), self.to_main_menu),
                menu.MenuItem(_("end_next_year"), self.next_year)]
        positions = [(config.SCREEN_WIDTH*0.2, 50),\
                     (config.SCREEN_WIDTH*0.8, 50)]
        self.create_menu(list, layout_strategy=menu.fixedPositionMenuLayout(positions))
        
    def to_main_menu(self):
        '''
        Returns to the main menu
        '''
        director.pop()
        
    def next_year(self):
        '''
        Starts the next year
        '''
        game.Game().new_year()
        
    def on_key_press(self, symbol, modifiers):
        if hasattr(self.end_layer, 'name_input') and self.end_layer.name_input:
            return False
        if symbol == key.ESCAPE:
            self.on_quit()
            return True
        elif symbol in (key.ENTER, key.NUM_ENTER):
            self._activate_item()
            return True
        elif symbol in (key.LEFT, key.RIGHT):
            if symbol == key.LEFT:
                new_idx = self.selected_index + 1
            elif symbol == key.RIGHT:
                new_idx = self.selected_index - 1

            if new_idx < 0:
                new_idx = len(self.children) -1
            elif new_idx > len(self.children) -1:
                new_idx = 0
            self._select_item( new_idx )
            return True
        elif symbol == pyglet.window.key.S and (modifiers & pyglet.window.key.MOD_ACCEL):
            dir = pyglet.resource.get_settings_path('MyGarden')
            if not os.path.exists(dir):
                os.makedirs(dir)
            filename = os.path.join(dir, 'MyGarden-%d.png')
            self.end_layer.showInfo(_("screenshot_saved"), 2.5)
            pyglet.image.get_buffer_manager().get_color_buffer().save(filename % (int( time.time() ) ) )
            return True
        else: return True
        
    def on_quit(self):
        self.to_main_menu()